<!DOCTYPE html>
<html lang="cn-ZH">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>Rust入门（十一）：智能指针 | 摸鱼老萌新</title>
    <meta name="description" content="Front end project and tips sharing">
    <link rel="stylesheet" href="/assets/style.8f1fef60.css">
    <link rel="modulepreload" href="/assets/app.75d9ecf2.js">
    <link rel="modulepreload" href="/assets/articles_rust_11.智能指针.md.48ecbccd.lean.js">
    
    <script id="check-dark-light">(()=>{const e=localStorage.getItem("vitepress-theme-appearance"),a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
  </head>
  <body>
    <div id="app"><div class="Layout" data-v-c6a644e1><!--[--><!--]--><!--[--><span tabindex="-1" data-v-151f2593></span><a href="#VPContent" class="VPSkipLink visually-hidden" data-v-151f2593> Skip to content </a><!--]--><!----><header class="VPNav" data-v-c6a644e1 data-v-a71a30f1><div class="VPNavBar has-sidebar" data-v-a71a30f1 data-v-6f1d18b5><div class="container" data-v-6f1d18b5><div class="VPNavBarTitle has-sidebar" data-v-6f1d18b5 data-v-d5925166><a class="title" href="/" data-v-d5925166><!--[--><!--]--><!--[--><img class="VPImage logo" src="/logo.jpg" data-v-e13a1912><!--]--><!--[-->摸鱼老萌新<!--]--><!--[--><!--]--></a></div><div class="content" data-v-6f1d18b5><!--[--><!--]--><!----><nav aria-labelledby="main-nav-aria-label" class="VPNavBarMenu menu" data-v-6f1d18b5 data-v-f83db6ba><span id="main-nav-aria-label" class="visually-hidden" data-v-f83db6ba>Main Navigation</span><!--[--><!--[--><div class="VPFlyout VPNavBarMenuGroup" data-v-f83db6ba data-v-6ffb57d3><button type="button" class="button" aria-haspopup="true" aria-expanded="false" data-v-6ffb57d3><span class="text" data-v-6ffb57d3><!----> 前端 <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="text-icon" data-v-6ffb57d3><path d="M12,16c-0.3,0-0.5-0.1-0.7-0.3l-6-6c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l5.3,5.3l5.3-5.3c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-6,6C12.5,15.9,12.3,16,12,16z"></path></svg></span></button><div class="menu" data-v-6ffb57d3><div class="VPMenu" data-v-6ffb57d3 data-v-1c5d0cfc><div class="items" data-v-1c5d0cfc><!--[--><!--[--><div class="VPMenuLink" data-v-1c5d0cfc data-v-e8e0fb1d><a class="VPLink link" href="/articles/basic/index.html" data-v-e8e0fb1d data-v-3c355974><!--[-->基础<!--]--><!----></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-1c5d0cfc data-v-e8e0fb1d><a class="VPLink link" href="/articles/vue/index.html" data-v-e8e0fb1d data-v-3c355974><!--[-->Vue<!--]--><!----></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-1c5d0cfc data-v-e8e0fb1d><a class="VPLink link" href="/articles/react/index.html" data-v-e8e0fb1d data-v-3c355974><!--[-->React<!--]--><!----></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-1c5d0cfc data-v-e8e0fb1d><a class="VPLink link" href="/articles/mini/index.html" data-v-e8e0fb1d data-v-3c355974><!--[-->小程序<!--]--><!----></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-1c5d0cfc data-v-e8e0fb1d><a class="VPLink link" href="/articles/electron/index.html" data-v-e8e0fb1d data-v-3c355974><!--[-->Electron<!--]--><!----></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-1c5d0cfc data-v-e8e0fb1d><a class="VPLink link" href="/articles/web3d/index.html" data-v-e8e0fb1d data-v-3c355974><!--[-->Web3D<!--]--><!----></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-1c5d0cfc data-v-e8e0fb1d><a class="VPLink link" href="/articles/rust/01.%E5%9F%BA%E7%A1%80%E5%85%A5%E9%97%A8.html" data-v-e8e0fb1d data-v-3c355974><!--[-->Rust<!--]--><!----></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-1c5d0cfc data-v-e8e0fb1d><a class="VPLink link" href="/articles/other/vitepress/01.vitepress%E7%9A%84%E6%90%AD%E5%BB%BA.html" data-v-e8e0fb1d data-v-3c355974><!--[-->其他<!--]--><!----></a></div><!--]--><!--]--></div><!--[--><!--]--></div></div></div><!--]--><!--[--><a class="VPLink link VPNavBarMenuLink" href="/leetcode/LEET_CODE%E9%A2%98%E8%A7%A3/47.%20%E5%85%A8%E6%8E%92%E5%88%97%20II.html" data-v-f83db6ba data-v-47a2263e data-v-3c355974><!--[-->算法<!--]--><!----></a><!--]--><!--[--><a class="VPLink link VPNavBarMenuLink" href="/intent/" data-v-f83db6ba data-v-47a2263e data-v-3c355974><!--[-->项目<!--]--><!----></a><!--]--><!--]--></nav><!----><div class="VPNavBarAppearance appearance" data-v-6f1d18b5 data-v-a3e7452b><button class="VPSwitch VPSwitchAppearance" type="button" role="switch" aria-label="toggle dark mode" aria-checked="false" data-v-a3e7452b data-v-1899cd41 data-v-086e8519><span class="check" data-v-086e8519><span class="icon" data-v-086e8519><!--[--><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="sun" data-v-1899cd41><path d="M12,18c-3.3,0-6-2.7-6-6s2.7-6,6-6s6,2.7,6,6S15.3,18,12,18zM12,8c-2.2,0-4,1.8-4,4c0,2.2,1.8,4,4,4c2.2,0,4-1.8,4-4C16,9.8,14.2,8,12,8z"></path><path d="M12,4c-0.6,0-1-0.4-1-1V1c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,3.6,12.6,4,12,4z"></path><path d="M12,24c-0.6,0-1-0.4-1-1v-2c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,23.6,12.6,24,12,24z"></path><path d="M5.6,6.6c-0.3,0-0.5-0.1-0.7-0.3L3.5,4.9c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C6.2,6.5,5.9,6.6,5.6,6.6z"></path><path d="M19.8,20.8c-0.3,0-0.5-0.1-0.7-0.3l-1.4-1.4c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C20.3,20.7,20,20.8,19.8,20.8z"></path><path d="M3,13H1c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S3.6,13,3,13z"></path><path d="M23,13h-2c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S23.6,13,23,13z"></path><path d="M4.2,20.8c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C4.7,20.7,4.5,20.8,4.2,20.8z"></path><path d="M18.4,6.6c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C18.9,6.5,18.6,6.6,18.4,6.6z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="moon" data-v-1899cd41><path d="M12.1,22c-0.3,0-0.6,0-0.9,0c-5.5-0.5-9.5-5.4-9-10.9c0.4-4.8,4.2-8.6,9-9c0.4,0,0.8,0.2,1,0.5c0.2,0.3,0.2,0.8-0.1,1.1c-2,2.7-1.4,6.4,1.3,8.4c2.1,1.6,5,1.6,7.1,0c0.3-0.2,0.7-0.3,1.1-0.1c0.3,0.2,0.5,0.6,0.5,1c-0.2,2.7-1.5,5.1-3.6,6.8C16.6,21.2,14.4,22,12.1,22zM9.3,4.4c-2.9,1-5,3.6-5.2,6.8c-0.4,4.4,2.8,8.3,7.2,8.7c2.1,0.2,4.2-0.4,5.8-1.8c1.1-0.9,1.9-2.1,2.4-3.4c-2.5,0.9-5.3,0.5-7.5-1.1C9.2,11.4,8.1,7.7,9.3,4.4z"></path></svg><!--]--></span></span></button></div><div class="VPSocialLinks VPNavBarSocialLinks social-links" data-v-6f1d18b5 data-v-738bef5a data-v-f6988cfb><!--[--><a class="VPSocialLink" href="https://github.com/aiai0603" target="_blank" rel="noopener" data-v-f6988cfb data-v-e57698f6><svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>GitHub</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></a><!--]--></div><div class="VPFlyout VPNavBarExtra extra" data-v-6f1d18b5 data-v-e89b88d7 data-v-6ffb57d3><button type="button" class="button" aria-haspopup="true" aria-expanded="false" aria-label="extra navigation" data-v-6ffb57d3><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="icon" data-v-6ffb57d3><circle cx="12" cy="12" r="2"></circle><circle cx="19" cy="12" r="2"></circle><circle cx="5" cy="12" r="2"></circle></svg></button><div class="menu" data-v-6ffb57d3><div class="VPMenu" data-v-6ffb57d3 data-v-1c5d0cfc><!----><!--[--><!--[--><!----><div class="group" data-v-e89b88d7><div class="item appearance" data-v-e89b88d7><p class="label" data-v-e89b88d7>Appearance</p><div class="appearance-action" data-v-e89b88d7><button class="VPSwitch VPSwitchAppearance" type="button" role="switch" aria-label="toggle dark mode" aria-checked="false" data-v-e89b88d7 data-v-1899cd41 data-v-086e8519><span class="check" data-v-086e8519><span class="icon" data-v-086e8519><!--[--><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="sun" data-v-1899cd41><path d="M12,18c-3.3,0-6-2.7-6-6s2.7-6,6-6s6,2.7,6,6S15.3,18,12,18zM12,8c-2.2,0-4,1.8-4,4c0,2.2,1.8,4,4,4c2.2,0,4-1.8,4-4C16,9.8,14.2,8,12,8z"></path><path d="M12,4c-0.6,0-1-0.4-1-1V1c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,3.6,12.6,4,12,4z"></path><path d="M12,24c-0.6,0-1-0.4-1-1v-2c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,23.6,12.6,24,12,24z"></path><path d="M5.6,6.6c-0.3,0-0.5-0.1-0.7-0.3L3.5,4.9c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C6.2,6.5,5.9,6.6,5.6,6.6z"></path><path d="M19.8,20.8c-0.3,0-0.5-0.1-0.7-0.3l-1.4-1.4c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C20.3,20.7,20,20.8,19.8,20.8z"></path><path d="M3,13H1c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S3.6,13,3,13z"></path><path d="M23,13h-2c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S23.6,13,23,13z"></path><path d="M4.2,20.8c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C4.7,20.7,4.5,20.8,4.2,20.8z"></path><path d="M18.4,6.6c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C18.9,6.5,18.6,6.6,18.4,6.6z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="moon" data-v-1899cd41><path d="M12.1,22c-0.3,0-0.6,0-0.9,0c-5.5-0.5-9.5-5.4-9-10.9c0.4-4.8,4.2-8.6,9-9c0.4,0,0.8,0.2,1,0.5c0.2,0.3,0.2,0.8-0.1,1.1c-2,2.7-1.4,6.4,1.3,8.4c2.1,1.6,5,1.6,7.1,0c0.3-0.2,0.7-0.3,1.1-0.1c0.3,0.2,0.5,0.6,0.5,1c-0.2,2.7-1.5,5.1-3.6,6.8C16.6,21.2,14.4,22,12.1,22zM9.3,4.4c-2.9,1-5,3.6-5.2,6.8c-0.4,4.4,2.8,8.3,7.2,8.7c2.1,0.2,4.2-0.4,5.8-1.8c1.1-0.9,1.9-2.1,2.4-3.4c-2.5,0.9-5.3,0.5-7.5-1.1C9.2,11.4,8.1,7.7,9.3,4.4z"></path></svg><!--]--></span></span></button></div></div></div><div class="group" data-v-e89b88d7><div class="item social-links" data-v-e89b88d7><div class="VPSocialLinks social-links-list" data-v-e89b88d7 data-v-f6988cfb><!--[--><a class="VPSocialLink" href="https://github.com/aiai0603" target="_blank" rel="noopener" data-v-f6988cfb data-v-e57698f6><svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>GitHub</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></a><!--]--></div></div></div><!--]--><!--]--></div></div></div><!--[--><!--]--><button type="button" class="VPNavBarHamburger hamburger" aria-label="mobile navigation" aria-expanded="false" aria-controls="VPNavScreen" data-v-6f1d18b5 data-v-e5dd9c1c><span class="container" data-v-e5dd9c1c><span class="top" data-v-e5dd9c1c></span><span class="middle" data-v-e5dd9c1c></span><span class="bottom" data-v-e5dd9c1c></span></span></button></div></div></div><!----></header><div class="VPLocalNav" data-v-c6a644e1 data-v-aac27d5e><button class="menu" aria-expanded="false" aria-controls="VPSidebarNav" data-v-aac27d5e><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="menu-icon" data-v-aac27d5e><path d="M17,11H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h14c0.6,0,1,0.4,1,1S17.6,11,17,11z"></path><path d="M21,7H3C2.4,7,2,6.6,2,6s0.4-1,1-1h18c0.6,0,1,0.4,1,1S21.6,7,21,7z"></path><path d="M21,15H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h18c0.6,0,1,0.4,1,1S21.6,15,21,15z"></path><path d="M17,19H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h14c0.6,0,1,0.4,1,1S17.6,19,17,19z"></path></svg><span class="menu-text" data-v-aac27d5e>Menu</span></button><a class="top-link" href="#" data-v-aac27d5e> Return to top </a></div><aside class="VPSidebar" data-v-c6a644e1 data-v-f332cb62><nav class="nav" id="VPSidebarNav" aria-labelledby="sidebar-aria-label" tabindex="-1" data-v-f332cb62><span class="visually-hidden" id="sidebar-aria-label" data-v-f332cb62> Sidebar Navigation </span><!--[--><div class="group" data-v-f332cb62><section class="VPSidebarGroup collapsible" data-v-f332cb62 data-v-2976c796><div class="title" role="button" data-v-2976c796><h2 class="title-text" data-v-2976c796>rust</h2><div class="action" data-v-2976c796><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewbox="0 0 24 24" class="icon minus" data-v-2976c796><path d="M19,2H5C3.3,2,2,3.3,2,5v14c0,1.7,1.3,3,3,3h14c1.7,0,3-1.3,3-3V5C22,3.3,20.7,2,19,2zM20,19c0,0.6-0.4,1-1,1H5c-0.6,0-1-0.4-1-1V5c0-0.6,0.4-1,1-1h14c0.6,0,1,0.4,1,1V19z"></path><path d="M16,11H8c-0.6,0-1,0.4-1,1s0.4,1,1,1h8c0.6,0,1-0.4,1-1S16.6,11,16,11z"></path></svg><svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" class="icon plus" data-v-2976c796><path d="M19,2H5C3.3,2,2,3.3,2,5v14c0,1.7,1.3,3,3,3h14c1.7,0,3-1.3,3-3V5C22,3.3,20.7,2,19,2z M20,19c0,0.6-0.4,1-1,1H5c-0.6,0-1-0.4-1-1V5c0-0.6,0.4-1,1-1h14c0.6,0,1,0.4,1,1V19z"></path><path d="M16,11h-3V8c0-0.6-0.4-1-1-1s-1,0.4-1,1v3H8c-0.6,0-1,0.4-1,1s0.4,1,1,1h3v3c0,0.6,0.4,1,1,1s1-0.4,1-1v-3h3c0.6,0,1-0.4,1-1S16.6,11,16,11z"></path></svg></div></div><div class="items" data-v-2976c796><!--[--><!--[--><a class="VPLink link link" href="/articles/rust/01.%E5%9F%BA%E7%A1%80%E5%85%A5%E9%97%A8.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>01.基础入门</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/rust/02.%E5%9F%BA%E7%A1%80%E8%AF%AD%E6%B3%95.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>02.基础语法</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/rust/03.%E6%8C%87%E9%92%88%E4%B8%8E%E5%86%85%E5%AD%98%E5%88%86%E9%85%8D.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>03.指针与内存分配</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/rust/04.%E7%A8%8B%E5%BA%8F%E7%BB%93%E6%9E%84%E5%92%8C%E5%BC%82%E5%B8%B8%E5%A4%84%E7%90%86.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>04.程序结构和异常处理</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/rust/05.%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E6%B3%9B%E5%9E%8B.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>05.数据结构与泛型</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/rust/06.trait%E4%B8%8E%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>06.trait与生命周期</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/rust/07.%E7%BC%96%E5%86%99%E6%B5%8B%E8%AF%95.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>07.编写测试</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/rust/08.%E6%9E%84%E5%BB%BA%E5%91%BD%E4%BB%A4%E8%A1%8C%E7%A8%8B%E5%BA%8F.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>08.构建命令行程序</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/rust/09.%E9%97%AD%E5%8C%85%E4%B8%8E%E8%BF%AD%E4%BB%A3%E5%99%A8.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>09.闭包与迭代器</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/rust/10.%E5%8F%91%E5%B8%83%E9%A1%B9%E7%9B%AE.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>10.发布项目</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link active" href="/articles/rust/11.%E6%99%BA%E8%83%BD%E6%8C%87%E9%92%88.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>11.智能指针</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/rust/12.%E5%B9%B6%E5%8F%91.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>12.并发</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/rust/13.%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>13.面向对象</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/rust/14.%E4%B8%8D%E5%AE%89%E5%85%A8Rust.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>14.不安全Rust</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/rust/15.%E9%AB%98%E7%BA%A7%E7%89%B9%E6%80%A7.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>15.高级特性</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/rust/16.%E6%89%8B%E5%86%99web%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%92%8C%E7%BA%BF%E7%A8%8B%E6%B1%A0.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>16.手写web服务器和线程池</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/rust/17.rust%E5%BC%82%E6%AD%A5%E7%BC%96%E7%A8%8B.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>17.rust异步编程</span><!--]--><!----></a><!----><!--]--><!--]--></div></section></div><div class="group" data-v-f332cb62><section class="VPSidebarGroup collapsible collapsed" data-v-f332cb62 data-v-2976c796><div class="title" role="button" data-v-2976c796><h2 class="title-text" data-v-2976c796>rustweb</h2><div class="action" data-v-2976c796><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewbox="0 0 24 24" class="icon minus" data-v-2976c796><path d="M19,2H5C3.3,2,2,3.3,2,5v14c0,1.7,1.3,3,3,3h14c1.7,0,3-1.3,3-3V5C22,3.3,20.7,2,19,2zM20,19c0,0.6-0.4,1-1,1H5c-0.6,0-1-0.4-1-1V5c0-0.6,0.4-1,1-1h14c0.6,0,1,0.4,1,1V19z"></path><path d="M16,11H8c-0.6,0-1,0.4-1,1s0.4,1,1,1h8c0.6,0,1-0.4,1-1S16.6,11,16,11z"></path></svg><svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" class="icon plus" data-v-2976c796><path d="M19,2H5C3.3,2,2,3.3,2,5v14c0,1.7,1.3,3,3,3h14c1.7,0,3-1.3,3-3V5C22,3.3,20.7,2,19,2z M20,19c0,0.6-0.4,1-1,1H5c-0.6,0-1-0.4-1-1V5c0-0.6,0.4-1,1-1h14c0.6,0,1,0.4,1,1V19z"></path><path d="M16,11h-3V8c0-0.6-0.4-1-1-1s-1,0.4-1,1v3H8c-0.6,0-1,0.4-1,1s0.4,1,1,1h3v3c0,0.6,0.4,1,1,1s1-0.4,1-1v-3h3c0.6,0,1-0.4,1-1S16.6,11,16,11z"></path></svg></div></div><div class="items" data-v-2976c796><!--[--><!--[--><a class="VPLink link link" href="/articles/rustweb/01.%E7%AE%80%E5%8D%95%20server.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>01.简单 server</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/rustweb/02.Actix.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>02.Actix</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/rustweb/03.%E8%BF%9E%E6%8E%A5%E6%95%B0%E6%8D%AE%E5%BA%93.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>03.连接数据库</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/rustweb/04.%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>04.错误处理</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/rustweb/05.%E5%AE%8C%E6%95%B4%E9%A1%B9%E7%9B%AE%E9%87%8D%E6%9E%84.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>05.完整项目重构</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/rustweb/06.%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%AB%AFweb%E5%BA%94%E7%94%A8.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>06.服务器端web应用</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/rustweb/07.WebAssembly.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>07.WebAssembly</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/rustweb/08.%E5%8F%91%E5%B8%83.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>08.发布</span><!--]--><!----></a><!----><!--]--><!--]--></div></section></div><!--]--></nav></aside><div class="VPContent has-sidebar" id="VPContent" data-v-c6a644e1 data-v-c95df128><div class="VPDoc has-sidebar has-aside" data-v-c95df128 data-v-37ebe389><div class="container" data-v-37ebe389><div class="aside" data-v-37ebe389><div class="aside-curtain" data-v-37ebe389></div><div class="aside-container" data-v-37ebe389><div class="aside-content" data-v-37ebe389><div class="VPDocAside" data-v-37ebe389 data-v-afc4c1a1><!--[--><!--]--><!--[--><!--]--><div class="VPDocAsideOutline" data-v-afc4c1a1 data-v-2865c0b0><div class="content" data-v-2865c0b0><div class="outline-marker" data-v-2865c0b0></div><div class="outline-title" data-v-2865c0b0>On this page</div><nav aria-labelledby="doc-outline-aria-label" data-v-2865c0b0><span class="visually-hidden" id="doc-outline-aria-label" data-v-2865c0b0> Table of Contents for current page </span><ul class="root" data-v-2865c0b0 data-v-1188541a><!--[--><!--]--></ul></nav></div></div><!--[--><!--]--><div class="spacer" data-v-afc4c1a1></div><!--[--><!--]--><!----><!--[--><!--]--><!--[--><!--]--></div></div></div></div><div class="content" data-v-37ebe389><div class="content-container" data-v-37ebe389><!--[--><!--]--><main class="main" data-v-37ebe389><div style="position:relative;" class="vp-doc _articles_rust_11_%E6%99%BA%E8%83%BD%E6%8C%87%E9%92%88" data-v-37ebe389><div><h1 id="rust入门（十一）：智能指针" tabindex="-1">Rust入门（十一）：智能指针 <a class="header-anchor" href="#rust入门（十一）：智能指针" aria-hidden="true">#</a></h1><p>智能指针（<em>smart pointers</em>）是一类数据结构，他们的表现类似指针，但是也拥有额外的元数据和功能。智能指针通常使用结构体实现。智能指针区别于常规结构体的显著特性在于其实现了 <code>Deref</code> 和 <code>Drop</code> trait。<code>Deref</code> trait 允许智能指针结构体实例表现的像引用一样，这样就可以编写既用于引用、又用于智能指针的代码。<code>Drop</code> trait 允许我们自定义当智能指针离开作用域时运行的代码。</p><h2 id="box-t" tabindex="-1"><code>Box&lt;T&gt;</code> <a class="header-anchor" href="#box-t" aria-hidden="true">#</a></h2><p>最简单直接的智能指针是 <em>box</em>，其类型是 <code>Box&lt;T&gt;</code>。 box 允许你将一个值放在堆上，留在栈上的则是指向堆数据的指针。它们多用于如下场景：</p><ul><li>当有一个在编译时未知大小的类型，而又想要在需要确切大小的上下文中使用这个类型值的时候</li><li>当有大量数据并希望在确保数据不被拷贝的情况下转移所有权的时候</li><li>当希望拥有一个值并只关心它的类型是否实现了特定 trait 而不是其具体类型的时候</li></ul><p>如下的定义，这里定义了变量 <code>b</code>，其值是一个指向被分配在堆上的值 <code>5</code> 的 <code>Box</code>，而在栈上存储了一个对应的引用，正如任何拥有数据所有权的值那样，当像 <code>b</code> 这样的 box 在 <code>main</code> 的末尾离开作用域时，它将被释放。这个释放过程作用于 box 本身（位于栈上）和它所指向的数据（位于堆上）。</p><div class="language-rust"><button class="copy"></button><span class="lang">rust</span><pre><code><span class="line"><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">main</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> b </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Box</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#F78C6C;">5</span><span style="color:#89DDFF;">);</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#82AAFF;">println!</span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">b = </span><span style="color:#89DDFF;">{}&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> b</span><span style="color:#89DDFF;">);</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p>单独使用box的场景不常见，但是他可以用在一些特殊的场合，如下：</p><p><em>cons list</em> 是一个来源于 Lisp 编程语言及其方言的数据结构，类似于其他语言的链表，cons list 的每一项都包含两个元素：当前项的值和下一项。其最后一项值包含一个叫做 <code>Nil</code> 的值且没有下一项。</p><div class="language-rust"><button class="copy"></button><span class="lang">rust</span><pre><code><span class="line"><span style="color:#C792EA;">enum</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">List</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#82AAFF;">Cons</span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">i32</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">List</span><span style="color:#89DDFF;">),</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#FFCB6B;">Nil</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">main</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> list </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">Cons</span><span style="color:#89DDFF;">(</span><span style="color:#F78C6C;">1</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">Cons</span><span style="color:#89DDFF;">(</span><span style="color:#F78C6C;">2</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">Cons</span><span style="color:#89DDFF;">(</span><span style="color:#F78C6C;">3</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Nil</span><span style="color:#89DDFF;">)));</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p>如上的例子会产生错误，因为Rust 需要在编译时知道类型占用多少空间，而 Rust 无法计算为了存放 <code>List</code> 值到底需要多少空间，但是因为 <code>Box&lt;T&gt;</code> 是一个指针，我们总是知道它需要多少空间，将例子修改成如下的样子就不会产生问题了：</p><div class="language-rust"><button class="copy"></button><span class="lang">rust</span><pre><code><span class="line"><span style="color:#C792EA;">enum</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">List</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#82AAFF;">Cons</span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">i32</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Box</span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">List</span><span style="color:#89DDFF;">&gt;),</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#FFCB6B;">Nil</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F78C6C;">use</span><span style="color:#FFCB6B;"> </span><span style="color:#F78C6C;">crate</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">List</span><span style="color:#89DDFF;">::{</span><span style="color:#FFCB6B;">Cons</span><span style="color:#89DDFF;">,</span><span style="color:#FFCB6B;"> Nil</span><span style="color:#89DDFF;">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">main</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> list </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">Cons</span><span style="color:#89DDFF;">(</span><span style="color:#F78C6C;">1</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Box</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#82AAFF;">Cons</span><span style="color:#89DDFF;">(</span><span style="color:#F78C6C;">2</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Box</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#82AAFF;">Cons</span><span style="color:#89DDFF;">(</span><span style="color:#F78C6C;">3</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Box</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">Nil</span><span style="color:#89DDFF;">))))));</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><h2 id="deref-trait" tabindex="-1">Deref trait <a class="header-anchor" href="#deref-trait" aria-hidden="true">#</a></h2><p>实现 <code>Deref</code> trait 允许我们重载 <strong>解引用运算符</strong>,通过这种方式实现 <code>Deref</code> trait 的智能指针可以被当作常规引用来对待:</p><p>常规引用是一个指针类型，一种理解指针的方式是将其看成指向储存在其他某处值的箭头。如下，创建了一个 <code>i32</code> 值的引用，接着使用解引用运算符来跟踪所引用的数据，如果希望对 <code>y</code> 的值做出断言，必须使用 <code>*y</code> 来追踪引用所指向的值（也就是 <strong>解引用</strong>）。一旦解引用了 <code>y</code>，就可以访问 <code>y</code> 所指向的整型值并可以与 <code>5</code> 做比较。</p><div class="language-rust"><button class="copy"></button><span class="lang">rust</span><pre><code><span class="line"><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">main</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> x </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">5</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> y </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&amp;</span><span style="color:#A6ACCD;">x</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#82AAFF;">assert_eq!</span><span style="color:#89DDFF;">(</span><span style="color:#F78C6C;">5</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> x</span><span style="color:#89DDFF;">);</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#82AAFF;">assert_eq!</span><span style="color:#89DDFF;">(</span><span style="color:#F78C6C;">5</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">*</span><span style="color:#A6ACCD;">y</span><span style="color:#89DDFF;">);</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p>可以使用 <code>Box&lt;T&gt;</code> 代替引用来重写如上的代码，解引用运算符也一样能工作</p><div class="language-rust"><button class="copy"></button><span class="lang">rust</span><pre><code><span class="line"><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">main</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> x </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">5</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> y </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Box</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">x</span><span style="color:#89DDFF;">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#82AAFF;">assert_eq!</span><span style="color:#89DDFF;">(</span><span style="color:#F78C6C;">5</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> x</span><span style="color:#89DDFF;">);</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#82AAFF;">assert_eq!</span><span style="color:#89DDFF;">(</span><span style="color:#F78C6C;">5</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">*</span><span style="color:#A6ACCD;">y</span><span style="color:#89DDFF;">);</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p>因为它实现了 <code>Deref</code> trait，由标准库提供，要求实现名为 <code>deref</code> 的方法，其借用 <code>self</code> 并返回一个内部数据的引用。</p><div class="language-rust"><button class="copy"></button><span class="lang">rust</span><pre><code><span class="line"><span style="color:#F78C6C;">use</span><span style="color:#FFCB6B;"> std</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">ops</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">Deref</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#C792EA;">struct</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">MyBox</span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">T</span><span style="color:#89DDFF;">&gt;(</span><span style="color:#FFCB6B;">T</span><span style="color:#89DDFF;">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F78C6C;">impl</span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">T</span><span style="color:#89DDFF;">&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">MyBox</span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">T</span><span style="color:#89DDFF;">&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">x</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">T</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">-&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">MyBox</span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">T</span><span style="color:#89DDFF;">&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#82AAFF;">MyBox</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">x</span><span style="color:#89DDFF;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#F78C6C;">impl</span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">T</span><span style="color:#89DDFF;">&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Deref</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">for</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">MyBox</span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">T</span><span style="color:#89DDFF;">&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">type</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Target</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">T</span><span style="color:#89DDFF;">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">deref</span><span style="color:#89DDFF;">(&amp;</span><span style="color:#A6ACCD;">self</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">-&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&amp;</span><span style="color:#A6ACCD;">Self</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">Target</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">&amp;</span><span style="color:#A6ACCD;">self</span><span style="color:#89DDFF;">.</span><span style="color:#F78C6C;">0</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p><code>deref</code> 方法体中写入了 <code>&amp;self.0</code>，这样 <code>deref</code> 返回了我希望通过 <code>*</code> 运算符访问的值的引用，当我们输入 <code>*y</code> 时，Rust 事实上在底层运行了如下代码：</p><div class="language-rust"><button class="copy"></button><span class="lang">rust</span><pre><code><span class="line"><span style="color:#89DDFF;">*(</span><span style="color:#A6ACCD;">y</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">deref</span><span style="color:#89DDFF;">())</span></span>
<span class="line"></span></code></pre></div><p>Deref 强制转换只能作用于实现了 <code>Deref</code> trait 的类型。Deref 强制转换将这样一个类型的引用转换为另一个类型的引用。例如 Deref 强制转换 可以将 <code>&amp;String</code> 转换为 <code>&amp;str</code>，因为 <code>String</code> 实现了 <code>Deref</code> trait 因此可以返回 <code>&amp;str</code>。Deref 强制转换的加入使得 Rust 程序员编写函数和方法调用时无需增加过多显式使用 <code>&amp;</code> 和 <code>*</code> 的引用和解引用。</p><div class="language-rust"><button class="copy"></button><span class="lang">rust</span><pre><code><span class="line"><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">hello</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">name</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&amp;</span><span style="color:#FFCB6B;">str</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#82AAFF;">println!</span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">Hello, </span><span style="color:#89DDFF;">{}</span><span style="color:#C3E88D;">!</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> name</span><span style="color:#89DDFF;">);</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">main</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> m </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">MyBox</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">String</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">from</span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">Rust</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">));</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#82AAFF;">hello</span><span style="color:#89DDFF;">(&amp;</span><span style="color:#A6ACCD;">m</span><span style="color:#89DDFF;">);</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p>这里使用 <code>&amp;m</code> 调用 <code>hello</code> 函数，其为 <code>MyBox&lt;String&gt;</code> 值的引用，因为示在 <code>MyBox&lt;T&gt;</code> 上实现了 <code>Deref</code> trait，Rust 可以通过 <code>deref</code> 调用将 <code>&amp;MyBox&lt;String&gt;</code> 变为 <code>&amp;String</code>，标准库中提供了 <code>String</code> 上的 <code>Deref</code> 实现，其会返回字符串 slice，Rust 再次调用 <code>deref</code> 将 <code>&amp;String</code> 变为 <code>&amp;str</code>，这就符合 <code>hello</code> 函数的定义了。Rust 会分析这些类型并使用任意多次 <code>Deref::deref</code> 调用以获得匹配参数的类型。这些解析都发生在编译时，所以利用 Deref 强制转换并没有运行时损耗。</p><p>Rust 在发现类型和 trait 实现满足三种情况时会进行 Deref 强制转换：</p><ul><li>当 <code>T: Deref&lt;Target=U&gt;</code> 时从 <code>&amp;T</code> 到 <code>&amp;U</code>。</li><li>当 <code>T: DerefMut&lt;Target=U&gt;</code> 时从 <code>&amp;mut T</code> 到 <code>&amp;mut U</code>。</li><li>当 <code>T: Deref&lt;Target=U&gt;</code> 时从 <code>&amp;mut T</code> 到 <code>&amp;U</code>。</li></ul><p>Rust 会将可变引用强转为不可变引用。但是反之是不可能的。因为根据借用规则，如果有一个可变引用，其必须是这些数据的唯一引用（否则程序将无法编译）。</p><h2 id="drop-trait" tabindex="-1">Drop trait <a class="header-anchor" href="#drop-trait" aria-hidden="true">#</a></h2><p>对于智能指针模式来说第二个重要的 trait 是 <code>Drop</code>，其允许我们在值要离开作用域时执行一些代码。指定在值离开作用域时应该执行的代码的方式是实现 <code>Drop</code> trait。<code>Drop</code> trait 要求实现一个叫做 <code>drop</code> 的方法，它获取一个 <code>self</code> 的可变引用。</p><div class="language-rust"><button class="copy"></button><span class="lang">rust</span><pre><code><span class="line"><span style="color:#C792EA;">struct</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">CustomSmartPointer</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    data</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">String</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F78C6C;">impl</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Drop</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">for</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">CustomSmartPointer</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">drop</span><span style="color:#89DDFF;">(&amp;</span><span style="color:#C792EA;">mut</span><span style="color:#A6ACCD;"> self</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#82AAFF;">println!</span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">Dropping CustomSmartPointer with data `</span><span style="color:#89DDFF;">{}</span><span style="color:#C3E88D;">`!</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> self</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">data</span><span style="color:#89DDFF;">);</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">main</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> c </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">CustomSmartPointer</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        data</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">String</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">from</span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">my stuff</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">),</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">};</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> d </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">CustomSmartPointer</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        data</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">String</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">from</span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">other stuff</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">),</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">};</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#82AAFF;">println!</span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">CustomSmartPointers created.</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">);</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p>当运行这个程序，会出现如下输出，当实例离开作用域 Rust 会自动调用 <code>drop</code>，并调用我们指定的代码。变量以被创建时相反的顺序被丢弃，所以 <code>d</code> 在 <code>c</code> 之前被丢弃</p><div class="language-rust"><button class="copy"></button><span class="lang">rust</span><pre><code><span class="line"><span style="color:#89DDFF;">$</span><span style="color:#A6ACCD;"> cargo run</span></span>
<span class="line"><span style="color:#A6ACCD;">   </span><span style="color:#FFCB6B;">Compiling</span><span style="color:#A6ACCD;"> drop</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">example v0</span><span style="color:#89DDFF;">.</span><span style="color:#F78C6C;">1</span><span style="color:#89DDFF;">.</span><span style="color:#F78C6C;">0</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">file</span><span style="color:#89DDFF;">:</span><span style="color:#676E95;">///projects/drop-example)</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#FFCB6B;">Finished</span><span style="color:#A6ACCD;"> dev </span><span style="color:#89DDFF;">[</span><span style="color:#A6ACCD;">unoptimized </span><span style="color:#89DDFF;">+</span><span style="color:#A6ACCD;"> debuginfo</span><span style="color:#89DDFF;">]</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">target</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">s</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">in</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">0</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">60s</span></span>
<span class="line"><span style="color:#A6ACCD;">     </span><span style="color:#FFCB6B;">Running</span><span style="color:#A6ACCD;"> `target</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">debug</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">drop</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">example`</span></span>
<span class="line"><span style="color:#FFCB6B;">CustomSmartPointers</span><span style="color:#A6ACCD;"> created</span><span style="color:#89DDFF;">.</span></span>
<span class="line"><span style="color:#FFCB6B;">Dropping</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">CustomSmartPointer</span><span style="color:#A6ACCD;"> with data `other stuff`</span><span style="color:#89DDFF;">!</span></span>
<span class="line"><span style="color:#FFCB6B;">Dropping</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">CustomSmartPointer</span><span style="color:#A6ACCD;"> with data `my stuff`</span><span style="color:#89DDFF;">!</span></span>
<span class="line"></span></code></pre></div><p>Rust 并不允许我们主动调用 <code>Drop</code> trait 的 <code>drop</code> 方法；当我们希望在作用域结束之前就强制释放变量的话，我们应该使用的是由标准库提供的 <code>std::mem::drop</code></p><div class="language-rust"><button class="copy"></button><span class="lang">rust</span><pre><code><span class="line"><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">main</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> c </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">CustomSmartPointer</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        data</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">String</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">from</span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">some data</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">),</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">};</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#82AAFF;">println!</span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">CustomSmartPointer created.</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">);</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#82AAFF;">drop</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">c</span><span style="color:#89DDFF;">);</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#82AAFF;">println!</span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">CustomSmartPointer dropped before the end of main.</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">);</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><h2 id="rc-t" tabindex="-1"><code>Rc&lt;T&gt;</code> <a class="header-anchor" href="#rc-t" aria-hidden="true">#</a></h2><p>Rust 有一个叫做 <code>Rc&lt;T&gt;</code> 的类型。其名称为引用计数（<em>reference counting</em>）的缩写。引用计数意味着记录一个值引用的数量来知晓这个值是否仍在被使用。</p><p><code>Rc&lt;T&gt;</code> 用于当我们希望在堆上分配一些内存供程序的多个部分读取，而且无法在编译时确定程序的哪一部分会最后结束使用它的时候。注意 <code>Rc&lt;T&gt;</code> 只能用于单线程场景。</p><div class="language-rust"><button class="copy"></button><span class="lang">rust</span><pre><code><span class="line"><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">main</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> a </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Rc</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#82AAFF;">Cons</span><span style="color:#89DDFF;">(</span><span style="color:#F78C6C;">5</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Rc</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#82AAFF;">Cons</span><span style="color:#89DDFF;">(</span><span style="color:#F78C6C;">10</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Rc</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">Nil</span><span style="color:#89DDFF;">)))));</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#82AAFF;">println!</span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">count after creating a = </span><span style="color:#89DDFF;">{}&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Rc</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">strong_count</span><span style="color:#89DDFF;">(&amp;</span><span style="color:#A6ACCD;">a</span><span style="color:#89DDFF;">));</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> b </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">Cons</span><span style="color:#89DDFF;">(</span><span style="color:#F78C6C;">3</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Rc</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">clone</span><span style="color:#89DDFF;">(&amp;</span><span style="color:#A6ACCD;">a</span><span style="color:#89DDFF;">));</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#82AAFF;">println!</span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">count after creating b = </span><span style="color:#89DDFF;">{}&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Rc</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">strong_count</span><span style="color:#89DDFF;">(&amp;</span><span style="color:#A6ACCD;">a</span><span style="color:#89DDFF;">));</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> c </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">Cons</span><span style="color:#89DDFF;">(</span><span style="color:#F78C6C;">4</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Rc</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">clone</span><span style="color:#89DDFF;">(&amp;</span><span style="color:#A6ACCD;">a</span><span style="color:#89DDFF;">));</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#82AAFF;">println!</span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">count after creating c = </span><span style="color:#89DDFF;">{}&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Rc</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">strong_count</span><span style="color:#89DDFF;">(&amp;</span><span style="color:#A6ACCD;">a</span><span style="color:#89DDFF;">));</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#82AAFF;">println!</span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">count after c goes out of scope = </span><span style="color:#89DDFF;">{}&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Rc</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">strong_count</span><span style="color:#89DDFF;">(&amp;</span><span style="color:#A6ACCD;">a</span><span style="color:#89DDFF;">));</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p>如上的例子：在程序中每个引用计数变化的点，会打印出引用计数，其值可以通过调用 <code>Rc::strong_count</code> 函数获得。我们能够看到 <code>a</code> 中 <code>Rc&lt;List&gt;</code> 的初始引用计数为1，接着每次调用 <code>clone</code>，计数会增加1，当 <code>c</code> 离开作用域时，计数减1。</p><div class="language-rust"><button class="copy"></button><span class="lang">rust</span><pre><code><span class="line"><span style="color:#89DDFF;">$</span><span style="color:#A6ACCD;"> cargo run</span></span>
<span class="line"><span style="color:#A6ACCD;">   </span><span style="color:#FFCB6B;">Compiling</span><span style="color:#A6ACCD;"> cons</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">list v0</span><span style="color:#89DDFF;">.</span><span style="color:#F78C6C;">1</span><span style="color:#89DDFF;">.</span><span style="color:#F78C6C;">0</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">file</span><span style="color:#89DDFF;">:</span><span style="color:#676E95;">///projects/cons-list)</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#FFCB6B;">Finished</span><span style="color:#A6ACCD;"> dev </span><span style="color:#89DDFF;">[</span><span style="color:#A6ACCD;">unoptimized </span><span style="color:#89DDFF;">+</span><span style="color:#A6ACCD;"> debuginfo</span><span style="color:#89DDFF;">]</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">target</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">s</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">in</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">0</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">45s</span></span>
<span class="line"><span style="color:#A6ACCD;">     </span><span style="color:#FFCB6B;">Running</span><span style="color:#A6ACCD;"> `target</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">debug</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">cons</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">list`</span></span>
<span class="line"><span style="color:#A6ACCD;">count after creating a </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">1</span></span>
<span class="line"><span style="color:#A6ACCD;">count after creating b </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">2</span></span>
<span class="line"><span style="color:#A6ACCD;">count after creating c </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">3</span></span>
<span class="line"><span style="color:#A6ACCD;">count after c goes out of scope </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">2</span></span>
<span class="line"></span></code></pre></div><h2 id="refcell" tabindex="-1">RefCell <a class="header-anchor" href="#refcell" aria-hidden="true">#</a></h2><p>内部可变性（<em>Interior mutability</em>）是 Rust 中的一个设计模式，它允许你即使在有不可变引用时也可以改变数据，这通常是借用规则所不允许的，例如对于引用和 <code>Box&lt;T&gt;</code>，借用规则的不可变性作用于编译时。</p><p>但是对于 <code>RefCell&lt;T&gt;</code>，这些不可变性作用于运行时，在运行时检查借用规则的好处则是允许出现特定内存安全的场景，而它们在编译时检查中是不允许的，类似于 <code>Rc&lt;T&gt;</code>，<code>RefCell&lt;T&gt;</code> 只能用于单线程场景。</p><p>借用规则的一个推论是当有一个不可变值时，不能可变地借用它。例如，如下代码不能编译：</p><div class="language-rust"><button class="copy"></button><span class="lang">rust</span><pre><code><span class="line"><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">main</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> x </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">5</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> y </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&amp;</span><span style="color:#C792EA;">mut</span><span style="color:#A6ACCD;"> x</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p>当创建不可变和可变引用时，我们分别使用 <code>&amp;</code> 和 <code>&amp;mut</code> 语法。对于 <code>RefCell&lt;T&gt;</code> 来说，使用 <code>borrow</code> 和 <code>borrow_mut</code> 方法，这属于 <code>RefCell&lt;T&gt;</code> 安全 API 的一部分。</p><p><code>borrow</code> 方法返回 <code>Ref&lt;T&gt;</code> 类型的智能指针，<code>borrow_mut</code> 方法返回 <code>RefMut&lt;T&gt;</code> 类型的智能指针。这两个类型都实现了 <code>Deref</code>，所以可以当作常规引用对待。</p><p><code>RefCell&lt;T&gt;</code> 记录当前有多少个活动的 <code>Ref&lt;T&gt;</code> 和 <code>RefMut&lt;T&gt;</code> 智能指针。每次调用 <code>borrow</code>，<code>RefCell&lt;T&gt;</code> 将活动的不可变借用计数加一。当 <code>Ref&lt;T&gt;</code> 值离开作用域时，不可变借用计数减一。就像编译时借用规则一样，<code>RefCell&lt;T&gt;</code> 在任何时候只允许有多个不可变借用或一个可变借用。</p><p>如果我们尝试违反这些规则，相比引用时的编译时错误，<code>RefCell&lt;T&gt;</code> 的实现会在运行时出现 panic，如下：这里为 <code>borrow_mut</code> 返回的 <code>RefMut</code> 智能指针创建了 <code>one_borrow</code> 变量。接着用相同的方式在变量 <code>two_borrow</code> 创建了另一个可变借用。这会在相同作用域中创建两个可变引用，这是不允许的。当运行库的测试时，编译时不会有任何错误，不过测试会失败</p><div class="language-rust"><button class="copy"></button><span class="lang">rust</span><pre><code><span class="line"><span style="color:#F78C6C;">impl</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Messenger</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">for</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">MockMessenger</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">send</span><span style="color:#89DDFF;">(&amp;</span><span style="color:#A6ACCD;">self</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> message</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&amp;</span><span style="color:#FFCB6B;">str</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">            </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">mut</span><span style="color:#A6ACCD;"> one_borrow </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> self</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">sent_messages</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">borrow_mut</span><span style="color:#89DDFF;">();</span></span>
<span class="line"><span style="color:#A6ACCD;">            </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">mut</span><span style="color:#A6ACCD;"> two_borrow </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> self</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">sent_messages</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">borrow_mut</span><span style="color:#89DDFF;">();</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">            one_borrow</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">push</span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">String</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">from</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">message</span><span style="color:#89DDFF;">));</span></span>
<span class="line"><span style="color:#A6ACCD;">            two_borrow</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">push</span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">String</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">from</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">message</span><span style="color:#89DDFF;">));</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p><code>RefCell&lt;T&gt;</code> 的一个常见用法是与 <code>Rc&lt;T&gt;</code> 结合。回忆一下 <code>Rc&lt;T&gt;</code> 允许对相同数据有多个所有者，不过只能提供数据的不可变访问。如果有一个储存了 <code>RefCell&lt;T&gt;</code> 的 <code>Rc&lt;T&gt;</code> 的话，就可以得到有多个所有者并且可以修改的值了</p><p>例如：cons list 的例子中使用 <code>Rc&lt;T&gt;</code> 使得多个列表共享另一个列表的所有权。因为 <code>Rc&lt;T&gt;</code> 只存放不可变值，所以一旦创建了这些列表值后就不能修改。让我们加入 <code>RefCell&lt;T&gt;</code> 来获得修改列表中值的能力。通过在 <code>Cons</code> 定义中使用 <code>RefCell&lt;T&gt;</code>，我们就允许修改所有列表中的值了：</p><div class="language-rust"><button class="copy"></button><span class="lang">rust</span><pre><code><span class="line"><span style="color:#89DDFF;">#[</span><span style="color:#A6ACCD;">derive</span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">Debug</span><span style="color:#89DDFF;">)]</span></span>
<span class="line"><span style="color:#C792EA;">enum</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">List</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#82AAFF;">Cons</span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">Rc</span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">RefCell</span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">i32</span><span style="color:#89DDFF;">&gt;&gt;,</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Rc</span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">List</span><span style="color:#89DDFF;">&gt;),</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#FFCB6B;">Nil</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F78C6C;">use</span><span style="color:#FFCB6B;"> </span><span style="color:#F78C6C;">crate</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">List</span><span style="color:#89DDFF;">::{</span><span style="color:#FFCB6B;">Cons</span><span style="color:#89DDFF;">,</span><span style="color:#FFCB6B;"> Nil</span><span style="color:#89DDFF;">};</span></span>
<span class="line"><span style="color:#F78C6C;">use</span><span style="color:#FFCB6B;"> std</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">cell</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">RefCell</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F78C6C;">use</span><span style="color:#FFCB6B;"> std</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">rc</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">Rc</span><span style="color:#89DDFF;">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">main</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> value </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Rc</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">RefCell</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#F78C6C;">5</span><span style="color:#89DDFF;">));</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> a </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Rc</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#82AAFF;">Cons</span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">Rc</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">clone</span><span style="color:#89DDFF;">(&amp;</span><span style="color:#A6ACCD;">value</span><span style="color:#89DDFF;">),</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Rc</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">Nil</span><span style="color:#89DDFF;">)));</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> b </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">Cons</span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">Rc</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">RefCell</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#F78C6C;">3</span><span style="color:#89DDFF;">)),</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Rc</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">clone</span><span style="color:#89DDFF;">(&amp;</span><span style="color:#A6ACCD;">a</span><span style="color:#89DDFF;">));</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> c </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">Cons</span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">Rc</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">RefCell</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#F78C6C;">4</span><span style="color:#89DDFF;">)),</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Rc</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">clone</span><span style="color:#89DDFF;">(&amp;</span><span style="color:#A6ACCD;">a</span><span style="color:#89DDFF;">));</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">*</span><span style="color:#A6ACCD;">value</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">borrow_mut</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">+=</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">10</span><span style="color:#89DDFF;">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#82AAFF;">println!</span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">a after = </span><span style="color:#89DDFF;">{</span><span style="color:#C3E88D;">:?</span><span style="color:#89DDFF;">}&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> a</span><span style="color:#89DDFF;">);</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#82AAFF;">println!</span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">b after = </span><span style="color:#89DDFF;">{</span><span style="color:#C3E88D;">:?</span><span style="color:#89DDFF;">}&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> b</span><span style="color:#89DDFF;">);</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#82AAFF;">println!</span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">c after = </span><span style="color:#89DDFF;">{</span><span style="color:#C3E88D;">:?</span><span style="color:#89DDFF;">}&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> c</span><span style="color:#89DDFF;">);</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#676E95;">//运行结果</span></span>
<span class="line"><span style="color:#89DDFF;">$</span><span style="color:#A6ACCD;"> cargo run</span></span>
<span class="line"><span style="color:#A6ACCD;">   </span><span style="color:#FFCB6B;">Compiling</span><span style="color:#A6ACCD;"> cons</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">list v0</span><span style="color:#89DDFF;">.</span><span style="color:#F78C6C;">1</span><span style="color:#89DDFF;">.</span><span style="color:#F78C6C;">0</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">file</span><span style="color:#89DDFF;">:</span><span style="color:#676E95;">///projects/cons-list)</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#FFCB6B;">Finished</span><span style="color:#A6ACCD;"> dev </span><span style="color:#89DDFF;">[</span><span style="color:#A6ACCD;">unoptimized </span><span style="color:#89DDFF;">+</span><span style="color:#A6ACCD;"> debuginfo</span><span style="color:#89DDFF;">]</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">target</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">s</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">in</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">0</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">63s</span></span>
<span class="line"><span style="color:#A6ACCD;">     </span><span style="color:#FFCB6B;">Running</span><span style="color:#A6ACCD;"> `target</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">debug</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">cons</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">list`</span></span>
<span class="line"><span style="color:#A6ACCD;">a after </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">Cons</span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">RefCell</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;"> value</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">15</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">},</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Nil</span><span style="color:#89DDFF;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">b after </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">Cons</span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">RefCell</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;"> value</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">3</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">},</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">Cons</span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">RefCell</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;"> value</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">15</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">},</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Nil</span><span style="color:#89DDFF;">))</span></span>
<span class="line"><span style="color:#A6ACCD;">c after </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">Cons</span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">RefCell</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;"> value</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">4</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">},</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">Cons</span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">RefCell</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;"> value</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">15</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">},</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Nil</span><span style="color:#89DDFF;">))</span></span>
<span class="line"></span></code></pre></div><p>通过使用 <code>RefCell&lt;T&gt;</code>，我们可以拥有一个表面上不可变的 <code>List</code>，不过可以使用 <code>RefCell&lt;T&gt;</code> 中提供内部可变性的方法来在需要时修改数据。<code>RefCell&lt;T&gt;</code> 的运行时借用规则检查也确实保护我们免于出现数据竞争——有时为了数据结构的灵活性而付出一些性能是值得的。</p><h2 id="引用循环" tabindex="-1">引用循环 <a class="header-anchor" href="#引用循环" aria-hidden="true">#</a></h2><p>Rust 的内存安全性保证使其难以意外地制造永远也不会被清理的内存,但并不是不可能 。通过 <code>Rc&lt;T&gt;</code> 和 <code>RefCell&lt;T&gt;</code> 看出：创建引用循环的可能性是存在的。这会造成内存泄漏，因为每一项的引用计数永远也到不了 0，其值也永远不会被丢弃。</p><p>如下：这些代码在 <code>a</code> 中创建了一个列表，一个指向 <code>a</code> 中列表的 <code>b</code> 列表，接着修改 <code>a</code> 中的列表指向 <code>b</code> 中的列表，这会创建一个引用循环。</p><div class="language-RUST"><button class="copy"></button><span class="lang">RUST</span><pre><code><span class="line"><span style="color:#F78C6C;">use</span><span style="color:#FFCB6B;"> </span><span style="color:#F78C6C;">crate</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">List</span><span style="color:#89DDFF;">::{</span><span style="color:#FFCB6B;">Cons</span><span style="color:#89DDFF;">,</span><span style="color:#FFCB6B;"> Nil</span><span style="color:#89DDFF;">};</span></span>
<span class="line"><span style="color:#F78C6C;">use</span><span style="color:#FFCB6B;"> std</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">cell</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">RefCell</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F78C6C;">use</span><span style="color:#FFCB6B;"> std</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">rc</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">Rc</span><span style="color:#89DDFF;">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#89DDFF;">#[</span><span style="color:#A6ACCD;">derive</span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">Debug</span><span style="color:#89DDFF;">)]</span></span>
<span class="line"><span style="color:#C792EA;">enum</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">List</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#82AAFF;">Cons</span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">i32</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">RefCell</span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">Rc</span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">List</span><span style="color:#89DDFF;">&gt;&gt;),</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#FFCB6B;">Nil</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F78C6C;">impl</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">List</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">tail</span><span style="color:#89DDFF;">(&amp;</span><span style="color:#A6ACCD;">self</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">-&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Option</span><span style="color:#89DDFF;">&lt;&amp;</span><span style="color:#FFCB6B;">RefCell</span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">Rc</span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">List</span><span style="color:#89DDFF;">&gt;&gt;&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">match</span><span style="color:#A6ACCD;"> self </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">            </span><span style="color:#82AAFF;">Cons</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">_</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> item</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">=&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Some</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">item</span><span style="color:#89DDFF;">),</span></span>
<span class="line"><span style="color:#A6ACCD;">            </span><span style="color:#FFCB6B;">Nil</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">=&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">None</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">main</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> a </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Rc</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#82AAFF;">Cons</span><span style="color:#89DDFF;">(</span><span style="color:#F78C6C;">5</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">RefCell</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">Rc</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">Nil</span><span style="color:#89DDFF;">))));</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#82AAFF;">println!</span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">a initial rc count = </span><span style="color:#89DDFF;">{}&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Rc</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">strong_count</span><span style="color:#89DDFF;">(&amp;</span><span style="color:#A6ACCD;">a</span><span style="color:#89DDFF;">));</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#82AAFF;">println!</span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">a next item = </span><span style="color:#89DDFF;">{</span><span style="color:#C3E88D;">:?</span><span style="color:#89DDFF;">}&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> a</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">tail</span><span style="color:#89DDFF;">());</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> b </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Rc</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#82AAFF;">Cons</span><span style="color:#89DDFF;">(</span><span style="color:#F78C6C;">10</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">RefCell</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">Rc</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">clone</span><span style="color:#89DDFF;">(&amp;</span><span style="color:#A6ACCD;">a</span><span style="color:#89DDFF;">))));</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#82AAFF;">println!</span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">a rc count after b creation = </span><span style="color:#89DDFF;">{}&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Rc</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">strong_count</span><span style="color:#89DDFF;">(&amp;</span><span style="color:#A6ACCD;">a</span><span style="color:#89DDFF;">));</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#82AAFF;">println!</span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">b initial rc count = </span><span style="color:#89DDFF;">{}&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Rc</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">strong_count</span><span style="color:#89DDFF;">(&amp;</span><span style="color:#A6ACCD;">b</span><span style="color:#89DDFF;">));</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#82AAFF;">println!</span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">b next item = </span><span style="color:#89DDFF;">{</span><span style="color:#C3E88D;">:?</span><span style="color:#89DDFF;">}&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> b</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">tail</span><span style="color:#89DDFF;">());</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">if</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Some</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">link</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> a</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">tail</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">*</span><span style="color:#A6ACCD;">link</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">borrow_mut</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Rc</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">clone</span><span style="color:#89DDFF;">(&amp;</span><span style="color:#A6ACCD;">b</span><span style="color:#89DDFF;">);</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#82AAFF;">println!</span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">b rc count after changing a = </span><span style="color:#89DDFF;">{}&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Rc</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">strong_count</span><span style="color:#89DDFF;">(&amp;</span><span style="color:#A6ACCD;">b</span><span style="color:#89DDFF;">));</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#82AAFF;">println!</span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">a rc count after changing a = </span><span style="color:#89DDFF;">{}&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Rc</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">strong_count</span><span style="color:#89DDFF;">(&amp;</span><span style="color:#A6ACCD;">a</span><span style="color:#89DDFF;">));</span></span>
<span class="line"></span>
<span class="line"><span style="color:#676E95;">    // Uncomment the next line to see that we have a cycle;</span></span>
<span class="line"><span style="color:#676E95;">    // it will overflow the stack</span></span>
<span class="line"><span style="color:#676E95;">    // println!(&quot;a next item = {:?}&quot;, a.tail());</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p>这里在变量 <code>a</code> 中创建了一个 <code>Rc&lt;List&gt;</code> 实例来存放初值为 <code>5, Nil</code> 的 <code>List</code> 值。接着在变量 <code>b</code> 中创建了存放包含值 10 和指向列表 <code>a</code> 的 <code>List</code> 的另一个 <code>Rc&lt;List&gt;</code> 实例。</p><p>可以看到将列表 <code>a</code> 修改为指向 <code>b</code> 之后， <code>a</code> 和 <code>b</code> 中的 <code>Rc&lt;List&gt;</code> 实例的引用计数都是 2。在 <code>main</code> 的结尾，Rust 丢弃 <code>b</code>，这会 <code>b</code> <code>Rc&lt;List&gt;</code> 实例的引用计数从 2 减为 1。然而，<code>b</code> <code>Rc&lt;List&gt;</code> 不能被回收，因为其引用计数是 1 而不是 0。接下来 Rust 会丢弃 <code>a</code> 将 <code>a</code> <code>Rc&lt;List&gt;</code> 实例的引用计数从 2 减为 1。这个实例也不能被回收，因为 <code>b</code> <code>Rc&lt;List&gt;</code> 实例依然引用它，所以其引用计数是 1。这些列表的内存将永远保持未被回收的状态</p><div class="language-rust"><button class="copy"></button><span class="lang">rust</span><pre><code><span class="line"><span style="color:#89DDFF;">$</span><span style="color:#A6ACCD;"> cargo run</span></span>
<span class="line"><span style="color:#A6ACCD;">   </span><span style="color:#FFCB6B;">Compiling</span><span style="color:#A6ACCD;"> cons</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">list v0</span><span style="color:#89DDFF;">.</span><span style="color:#F78C6C;">1</span><span style="color:#89DDFF;">.</span><span style="color:#F78C6C;">0</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">file</span><span style="color:#89DDFF;">:</span><span style="color:#676E95;">///projects/cons-list)</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#FFCB6B;">Finished</span><span style="color:#A6ACCD;"> dev </span><span style="color:#89DDFF;">[</span><span style="color:#A6ACCD;">unoptimized </span><span style="color:#89DDFF;">+</span><span style="color:#A6ACCD;"> debuginfo</span><span style="color:#89DDFF;">]</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">target</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">s</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">in</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">0</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">53s</span></span>
<span class="line"><span style="color:#A6ACCD;">     </span><span style="color:#FFCB6B;">Running</span><span style="color:#A6ACCD;"> `target</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">debug</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">cons</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">list`</span></span>
<span class="line"><span style="color:#A6ACCD;">a initial rc count </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">1</span></span>
<span class="line"><span style="color:#A6ACCD;">a next item </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Some</span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">RefCell</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;"> value</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Nil</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">})</span></span>
<span class="line"><span style="color:#A6ACCD;">a rc count after b creation </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">2</span></span>
<span class="line"><span style="color:#A6ACCD;">b initial rc count </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">1</span></span>
<span class="line"><span style="color:#A6ACCD;">b next item </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Some</span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">RefCell</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;"> value</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">Cons</span><span style="color:#89DDFF;">(</span><span style="color:#F78C6C;">5</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">RefCell</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;"> value</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Nil</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">})</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">})</span></span>
<span class="line"><span style="color:#A6ACCD;">b rc count after changing a </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">2</span></span>
<span class="line"><span style="color:#A6ACCD;">a rc count after changing a </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">2</span></span>
<span class="line"></span></code></pre></div><p>你可以通过调用 <code>Rc::downgrade</code> 并传递 <code>Rc&lt;T&gt;</code> 实例的引用来创建其值的 <strong>弱引用</strong>（<em>weak reference</em>）。调用 <code>Rc::downgrade</code> 时会得到 <code>Weak&lt;T&gt;</code> 类型的智能指针。不同于将 <code>Rc&lt;T&gt;</code> 实例的 <code>strong_count</code> 加 1，调用 <code>Rc::downgrade</code> 会将 <code>weak_count</code> 加 1。<code>Rc&lt;T&gt;</code> 类型使用 <code>weak_count</code> 来记录其存在多少个 <code>Weak&lt;T&gt;</code> 引用，类似于 <code>strong_count</code>。其区别在于 <code>weak_count</code> 无需计数为 0 就能使 <code>Rc&lt;T&gt;</code> 实例被清理。</p><p>强引用代表如何共享 <code>Rc&lt;T&gt;</code> 实例的所有权，但弱引用并不属于所有权关系。他们不会造成引用循环，因为任何弱引用的循环会在其相关的强引用计数为 0 时被打断。</p><p>因为 <code>Weak&lt;T&gt;</code> 引用的值可能已经被丢弃了，为了使用 <code>Weak&lt;T&gt;</code> 所指向的值，我们必须确保其值仍然有效。为此可以调用 <code>Weak&lt;T&gt;</code> 实例的 <code>upgrade</code> 方法，这会返回 <code>Option&lt;Rc&lt;T&gt;&gt;</code>。如果 <code>Rc&lt;T&gt;</code> 值还未被丢弃，则结果是 <code>Some</code>；如果 <code>Rc&lt;T&gt;</code> 已被丢弃，则结果是 <code>None</code>。因为 <code>upgrade</code> 返回一个 <code>Option&lt;Rc&lt;T&gt;&gt;</code>，Rust 会确保处理 <code>Some</code> 和 <code>None</code> 的情况，所以它不会返回非法指针。</p><p>如下：我们构建一个带有子节点的树，我们希望能够 <code>Node</code> 拥有其子节点，同时也希望通过变量来共享所有权，以便可以直接访问树中的每一个 <code>Node</code>，为此 <code>Vec&lt;T&gt;</code> 的项的类型被定义为 <code>Rc&lt;Node&gt;</code>。我们还希望能修改其他节点的子节点，所以 <code>children</code> 中 <code>Vec&lt;Rc&lt;Node&gt;&gt;</code> 被放进了 <code>RefCell&lt;T&gt;</code>。</p><div class="language-rust"><button class="copy"></button><span class="lang">rust</span><pre><code><span class="line"><span style="color:#F78C6C;">use</span><span style="color:#FFCB6B;"> std</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">cell</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">RefCell</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F78C6C;">use</span><span style="color:#FFCB6B;"> std</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">rc</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">Rc</span><span style="color:#89DDFF;">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#89DDFF;">#[</span><span style="color:#A6ACCD;">derive</span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">Debug</span><span style="color:#89DDFF;">)]</span></span>
<span class="line"><span style="color:#C792EA;">struct</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Node</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    value</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">i32</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">    children</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">RefCell</span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">Vec</span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">Rc</span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">Node</span><span style="color:#89DDFF;">&gt;&gt;&gt;,</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p>接下来，使用此结构体定义来创建一个叫做 <code>leaf</code> 的带有值 3 且没有子节点的 <code>Node</code> 实例，和另一个带有值 5 并以 <code>leaf</code> 作为子节点的实例 <code>branch</code>，这里克隆了 <code>leaf</code> 中的 <code>Rc&lt;Node&gt;</code> 并储存在了 <code>branch</code> 中，这意味着 <code>leaf</code> 中的 <code>Node</code> 现在有两个所有者：<code>leaf</code>和<code>branch</code>。可以通过 <code>branch.children</code> 从 <code>branch</code> 中获得 <code>leaf</code>，不过无法从 <code>leaf</code> 到 <code>branch</code>。</p><div class="language-rust"><button class="copy"></button><span class="lang">rust</span><pre><code><span class="line"><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">main</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> leaf </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Rc</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">Node</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        value</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">3</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">        children</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">RefCell</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#82AAFF;">vec!</span><span style="color:#89DDFF;">[]),</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">});</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> branch </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Rc</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">Node</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        value</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">5</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">        children</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">RefCell</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#82AAFF;">vec!</span><span style="color:#89DDFF;">[</span><span style="color:#FFCB6B;">Rc</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">clone</span><span style="color:#89DDFF;">(&amp;</span><span style="color:#A6ACCD;">leaf</span><span style="color:#89DDFF;">)]),</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">});</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p>为了使子节点知道其父节点，需要在 <code>Node</code> 结构体定义中增加一个 <code>parent</code> 字段。问题是 <code>parent</code> 的类型应该是什么。我们知道其不能包含 <code>Rc&lt;T&gt;</code>，因为这样 <code>leaf.parent</code> 将会指向 <code>branch</code> 而 <code>branch.children</code> 会包含 <code>leaf</code> 的指针，这会形成引用循环，所以 <code>parent</code> 使用 <code>Weak&lt;T&gt;</code> 类型而不是 <code>Rc&lt;T&gt;</code>，具体来说是 <code>RefCell&lt;Weak&lt;Node&gt;&gt;</code>。现在 <code>Node</code> 结构体定义看起来像这样：</p><div class="language-rust"><button class="copy"></button><span class="lang">rust</span><pre><code><span class="line"><span style="color:#F78C6C;">use</span><span style="color:#FFCB6B;"> std</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">cell</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">RefCell</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F78C6C;">use</span><span style="color:#FFCB6B;"> std</span><span style="color:#89DDFF;">::</span><span style="color:#FFCB6B;">rc</span><span style="color:#89DDFF;">::{</span><span style="color:#FFCB6B;">Rc</span><span style="color:#89DDFF;">,</span><span style="color:#FFCB6B;"> Weak</span><span style="color:#89DDFF;">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#89DDFF;">#[</span><span style="color:#A6ACCD;">derive</span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">Debug</span><span style="color:#89DDFF;">)]</span></span>
<span class="line"><span style="color:#C792EA;">struct</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Node</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    value</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">i32</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">    parent</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">RefCell</span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">Weak</span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">Node</span><span style="color:#89DDFF;">&gt;&gt;,</span></span>
<span class="line"><span style="color:#A6ACCD;">    children</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">RefCell</span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">Vec</span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">Rc</span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">Node</span><span style="color:#89DDFF;">&gt;&gt;&gt;,</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F78C6C;">fn</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">main</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> leaf </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Rc</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">Node</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        value</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">3</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">        parent</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">RefCell</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">Weak</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">()),</span></span>
<span class="line"><span style="color:#A6ACCD;">        children</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">RefCell</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#82AAFF;">vec!</span><span style="color:#89DDFF;">[]),</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">});</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#82AAFF;">println!</span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">leaf parent = </span><span style="color:#89DDFF;">{</span><span style="color:#C3E88D;">:?</span><span style="color:#89DDFF;">}&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> leaf</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">parent</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">borrow</span><span style="color:#89DDFF;">().</span><span style="color:#82AAFF;">upgrade</span><span style="color:#89DDFF;">());</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> branch </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Rc</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">Node</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        value</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">5</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">        parent</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">RefCell</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">Weak</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">()),</span></span>
<span class="line"><span style="color:#A6ACCD;">        children</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">RefCell</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">new</span><span style="color:#89DDFF;">(</span><span style="color:#82AAFF;">vec!</span><span style="color:#89DDFF;">[</span><span style="color:#FFCB6B;">Rc</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">clone</span><span style="color:#89DDFF;">(&amp;</span><span style="color:#A6ACCD;">leaf</span><span style="color:#89DDFF;">)]),</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">});</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">*</span><span style="color:#A6ACCD;">leaf</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">parent</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">borrow_mut</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Rc</span><span style="color:#89DDFF;">::</span><span style="color:#82AAFF;">downgrade</span><span style="color:#89DDFF;">(&amp;</span><span style="color:#A6ACCD;">branch</span><span style="color:#89DDFF;">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#82AAFF;">println!</span><span style="color:#89DDFF;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">leaf parent = </span><span style="color:#89DDFF;">{</span><span style="color:#C3E88D;">:?</span><span style="color:#89DDFF;">}&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> leaf</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">parent</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">borrow</span><span style="color:#89DDFF;">().</span><span style="color:#82AAFF;">upgrade</span><span style="color:#89DDFF;">());</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p>这样，一个节点就能够引用其父节点，但不拥有其父节点。当创建 <code>branch</code> 节点时，其也会新建一个 <code>Weak&lt;Node&gt;</code> 引用，因为 <code>branch</code> 并没有父节点。<code>leaf</code> 仍然作为 <code>branch</code> 的一个子节点。一旦在 <code>branch</code> 中有了 <code>Node</code> 实例，就可以修改 <code>leaf</code> 使其拥有指向父节点的 <code>Weak&lt;Node&gt;</code> 引用。这里使用了 <code>leaf</code> 中 <code>parent</code> 字段里的 <code>RefCell&lt;Weak&lt;Node&gt;&gt;</code> 的 <code>borrow_mut</code> 方法，接着使用了 <code>Rc::downgrade</code> 函数来从 <code>branch</code> 中的 <code>Rc&lt;Node&gt;</code> 值创建了一个指向 <code>branch</code> 的 <code>Weak&lt;Node&gt;</code> 引用。当再次打印出 <code>leaf</code> 的父节点时，这一次将会得到存放了 <code>branch</code> 的 <code>Some</code> 值：现在 <code>leaf</code> 可以访问其父节点了！当打印出 <code>leaf</code> 时，我们也避免了最终会导致栈溢出的循环：<code>Weak&lt;Node&gt;</code> 引用被打印为 <code>(Weak)</code>：</p><div class="language-rust"><button class="copy"></button><span class="lang">rust</span><pre><code><span class="line"><span style="color:#A6ACCD;">leaf parent </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">Some</span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">Node</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;"> value</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">5</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> parent</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">RefCell</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;"> value</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">Weak</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">},</span></span>
<span class="line"><span style="color:#A6ACCD;">children</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">RefCell</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;"> value</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">[</span><span style="color:#FFCB6B;">Node</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;"> value</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">3</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> parent</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">RefCell</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;"> value</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">(</span><span style="color:#FFCB6B;">Weak</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">},</span></span>
<span class="line"><span style="color:#A6ACCD;">children</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">RefCell</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;"> value</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">[]</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">}]</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">})</span></span>
<span class="line"></span></code></pre></div></div></div></main><!--[--><!--]--><footer class="VPDocFooter" data-v-37ebe389 data-v-a54a85bd><!----><div class="prev-next" data-v-a54a85bd><div class="pager" data-v-a54a85bd><a class="pager-link prev" href="/articles/rust/10.%E5%8F%91%E5%B8%83%E9%A1%B9%E7%9B%AE.html" data-v-a54a85bd><span class="desc" data-v-a54a85bd>Previous page</span><span class="title" data-v-a54a85bd>10.发布项目</span></a></div><div class="has-prev pager" data-v-a54a85bd><a class="pager-link next" href="/articles/rust/12.%E5%B9%B6%E5%8F%91.html" data-v-a54a85bd><span class="desc" data-v-a54a85bd>Next page</span><span class="title" data-v-a54a85bd>12.并发</span></a></div></div></footer><!--[--><!--]--></div></div></div></div></div><!----><!--[--><!--]--></div></div>
    <script>__VP_HASH_MAP__ = JSON.parse("{\"articles_basic-bitdance_class01-html.md\":\"ff4ff513\",\"articles_basic-bitdance_class02-css.md\":\"a702a9f8\",\"articles_basic-bitdance_class03-js.md\":\"0cf4e640\",\"articles_basic-bitdance_class04-typescript.md\":\"6eb8a62e\",\"articles_basic-bitdance_class05-http.md\":\"cb129388\",\"articles_basic-bitdance_class06-react.md\":\"a4c71f1a\",\"articles_basic-bitdance_class07-node.md\":\"7925a6b7\",\"articles_basic-bitdance_class08-next.js.md\":\"893eef63\",\"articles_basic-bitdance_class08.5-开发技巧.md\":\"e6d7e150\",\"articles_basic-bitdance_class09-跨端技术.md\":\"25156c46\",\"articles_basic-bitdance_class10-调试.md\":\"f07f60c2\",\"articles_basic-bitdance_class11-安全.md\":\"3c992463\",\"articles_basic-bitdance_class12-监控sdk.md\":\"35ef00f1\",\"articles_basic-bitdance_class13-webpack.md\":\"70e5acc7\",\"articles_basic-bitdance_class14-vite.md\":\"9cfa31e3\",\"articles_basic-bitdance_class15-可视化.md\":\"4c9a2433\",\"articles_basic_index.md\":\"5c1f50b5\",\"articles_electron_index.md\":\"acb5a448\",\"articles_electron_测试.md\":\"5404a20a\",\"articles_mini_index.md\":\"9af79c7b\",\"articles_other_vitepress_01.vitepress的搭建.md\":\"b8deb5b2\",\"articles_other_vitepress_02.vitepress的部署.md\":\"cf416a09\",\"articles_other_vitepress_03.vitepress自动生成目录.md\":\"0dd6d021\",\"articles_other_vitepress_04.vitepress引入vue组件.md\":\"46052034\",\"articles_react_index.md\":\"ec69e04d\",\"articles_react_source code_01.react的架构.md\":\"f4181c9b\",\"articles_rust_01.基础入门.md\":\"af35ebe7\",\"articles_rust_02.基础语法.md\":\"eba033ca\",\"articles_rust_03.指针与内存分配.md\":\"b6d4df62\",\"articles_rust_04.程序结构和异常处理.md\":\"07567152\",\"articles_rust_05.数据结构与泛型.md\":\"6d5c530d\",\"articles_rust_06.trait与生命周期.md\":\"5e57b7aa\",\"articles_rust_07.编写测试.md\":\"bd7d6015\",\"articles_rust_08.构建命令行程序.md\":\"a295a848\",\"articles_rust_09.闭包与迭代器.md\":\"cf79a80f\",\"articles_rust_10.发布项目.md\":\"9e4f6be1\",\"articles_rust_11.智能指针.md\":\"48ecbccd\",\"articles_rust_12.并发.md\":\"62f8f67e\",\"articles_rust_13.面向对象.md\":\"a8519b1a\",\"articles_rust_14.不安全rust.md\":\"a079df80\",\"articles_rust_15.高级特性.md\":\"2b09c61c\",\"articles_rust_16.手写web服务器和线程池.md\":\"97f59e40\",\"articles_rust_17.rust异步编程.md\":\"e26606a3\",\"articles_rustweb_01.简单 server.md\":\"6c2ab750\",\"articles_rustweb_02.actix.md\":\"048a9c59\",\"articles_rustweb_03.连接数据库.md\":\"5ccb794e\",\"articles_rustweb_04.错误处理.md\":\"bd3759f6\",\"articles_rustweb_05.完整项目重构.md\":\"d160a226\",\"articles_rustweb_06.服务器端web应用.md\":\"cdc4f4ca\",\"articles_rustweb_07.webassembly.md\":\"0f1bc773\",\"articles_rustweb_08.发布.md\":\"d4792485\",\"articles_vue_index.md\":\"5ded6ffa\",\"articles_vue组件库_vue3组件库项目学习笔记（1）：基础搭建.md\":\"23c5186c\",\"articles_vue组件库_vue3组件库项目学习笔记（2）：开发一个组件.md\":\"fdd9e315\",\"articles_vue组件库_vue3组件库项目学习笔记（3）：测试你的组件.md\":\"7a02b7b2\",\"articles_vue组件库_vue3组件库项目学习笔记（4）：发布你的组件.md\":\"e0b3816e\",\"articles_vue组件库_vue3组件库项目学习笔记（5）：配置编码规范.md\":\"291e9a8e\",\"articles_vue组件库_vue3组件库项目学习笔记（6）：发布组件文档.md\":\"3fa49d31\",\"articles_vue组件库_vue3组件库项目学习笔记（7）：正式开发问题拾遗.md\":\"85204ad9\",\"articles_vue组件库_vue3组件库项目学习笔记（8）：git协作.md\":\"ab61313a\",\"articles_web3d_index.md\":\"a52fc82e\",\"index.md\":\"de494fc0\",\"intent_index.md\":\"82efde64\",\"leetcode_leet_code题解_47. 全排列 ii.md\":\"c8680b3d\",\"leetcode_leet_code题解_49. 字母异位词分组.md\":\"e37b3116\",\"leetcode_leet_code题解_55. 跳跃游戏.md\":\"29658916\",\"leetcode_leet_code题解_56. 合并区间.md\":\"8f16bd71\",\"public_draco_readme.md\":\"5da4c955\"}")</script>
    <script type="module" async src="/assets/app.75d9ecf2.js"></script>
    
  </body>
</html>